/*
 * Diego da Rocha Borges
 * Otávio Zabaleta
 */

%{
#include "stdio.h"
#include "global.h"
#include "symbol_table.h"
#include "ast.h"
#include "y.tab.h"

int lineNumber;
int running;
extern HASH_TABLE* table;

HASH_NODE* symbol;

void set_symbol(HASH_NODE* symbol);

%}

/* Definition of scopes for comments */
%x COM_MULT_LINE


DIGIT                   [0-9]
LETTER                  [A-Za-z]
SINGLE_CHAR_OP          (","|";"|":"|"("|")"|"{"|"}"|"["|"]"|"+"|"*"|"/"|"-"|"<"|">"|"="|"!")
%%

">"                                         { return OPERATOR_G; }
"<"                                         { return OPERATOR_L; }
"<="										{ return OPERATOR_LE; }
">="										{ return OPERATOR_GE; }
"=="										{ return OPERATOR_EQ; }
"!="										{ return OPERATOR_NE; }
"or"										{ return OPERATOR_OR; }
"&&"										{ return OPERATOR_AND; }

int											{ return KW_INT; }
byte                                      	{ return KW_BYTE; }
if											{ return KW_IF; }
then										{ return KW_THEN; }
else										{ return KW_ELSE; }
while										{ return KW_WHILE; }
print										{ return KW_PRINT; }
return 										{ return KW_RETURN; }
read                                      	{ return KW_READ; }

{SINGLE_CHAR_OP}                            { return (int)yytext[0]; } //returns the char to yacc

{LETTER}(_|{LETTER}|{DIGIT})*               {
												symbol = hash_insert_entry(table, yytext, SYMBOL_IDENTIFIER, getLineNumber());
                                                set_symbol(symbol);
												return TK_IDENTIFIER;
											}

{DIGIT}+									{
												symbol = hash_insert_entry(table, yytext, SYMBOL_LIT_INTEGER, getLineNumber());
                                                set_symbol(symbol);
												return LIT_INTEGER;
											}

\'.\'                             			{
												symbol = hash_insert_entry(table, remove_quotes(yytext), SYMBOL_LIT_CHAR, getLineNumber());
                                                set_symbol(symbol);
												return LIT_CHAR;
											}

L?\"(\\\\.|[^\\"])*\"							{
												symbol = hash_insert_entry(table, remove_quotes(yytext), SYMBOL_LIT_STRING, getLineNumber());
                                                set_symbol(symbol);
												return LIT_STRING;
											}

\n											{ ++lineNumber; }

"//".*                                      { }

"/*"										BEGIN(COM_MULT_LINE);
<COM_MULT_LINE>"*/"							BEGIN(INITIAL);
<COM_MULT_LINE>. 							{ }
<COM_MULT_LINE>\n							{ ++lineNumber; }

[ |\t]+                             		{ }
.											{ printf("unexpected token: %s\n", yytext); return TOKEN_ERROR; }

%%
void set_symbol(HASH_NODE* symbol) {
    yylval.symbol = symbol;
}

int getLineNumber(void)
{
    return lineNumber;
}

void initMe(void)
{
    running = 1;
    lineNumber = 1;
    table = malloc(sizeof(HASH_TABLE));
    hash_init(table);
}

char* remove_quotes(char* lexeme)
{
    int lexeme_lenth = strlen(lexeme);
    char* new_lexeme = malloc((lexeme_lenth + 2) * sizeof(char));
    strncpy(new_lexeme, lexeme+1,lexeme_lenth-2);
    return new_lexeme;
}

/*
 * This function will be called when the scanner finish to process the lexemas.
 */
int yywrap()
{
    running = 0;
    return 1;
}